//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security;
using System.Security.Permissions;
using ManagementStudioServices.Interfaces;
using Microsoft.Research.ScientificWorkflow.ManagementStudioModels;
using Microsoft.Research.ScientificWorkflow.TridentUtilities;
using Microsoft.Win32;
using SR = Microsoft.Research.DataLayer;
using Microsoft.Research.ScientificWorkflow.TridentComposer;

namespace ManagementStudioServices
{
    /// <summary>
    /// The helper class which performs the DB calls for data required by the UI.
    /// </summary>
    public class WorkflowManagerService : IWorkflowManagerService
    {

        /// <summary>
        /// This is used to access registry connection.
        /// </summary>
        private SR.Connection registryConnection;

        private const string DATETIMEFORMAT = "dd MMM yy HH_mm_ss";

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="registryConnection">The registry connection.</param>
        public WorkflowManagerService(SR.Connection registryConnection)
        {
            this.registryConnection = registryConnection;
        }

        #region IWorkflowManagerService Members

        public SR.Connection CurrentConnection
        {
            get { return registryConnection; }
        }

        /// <summary>
        /// Retreive all the available workflows from the registry.
        /// </summary>
        public Collection<SR.Activity> GetAvailableWorkflows(SR.Activity.ISearch.ISearchClause filter)
        {
            return this.GetWorkflows(filter);
        }

        /// <summary>
        /// Retreive all the currently running jobs from the registry.
        /// </summary>
        /// <param name="queryString"></param>
        /// <returns></returns>
        public Collection<SR.Job> GetRunningWorkflows(SR.Job.ISearch.ISearchClause filter)
        {
            return this.GetRunningJobs(filter);
        }


        /// <summary>
        /// Retreive the deleted workflows from the registry.
        /// </summary>
        /// <param name="queryString"></param>
        /// <returns></returns>
        public Collection<SR.Activity> GetDeletedWorkflows(SR.Activity.ISearch.ISearchClause filter)
        {
            return this.GetAllDeletedWorkflows(filter);
        }

        /// <summary>
        /// Retrieve the completed jobs from the registry.
        /// </summary>
        /// <param name="queryString"></param>
        /// <returns></returns>
        public Collection<SR.Job> GetCompletedJobs(SR.Job.ISearch.ISearchClause filter)
        {
            return this.GetMyCompletedJobs(filter);
        }

        /// <summary>
        /// Retreive the jobs of the specified workflow.
        /// </summary>
        /// <param name="workflowId">The workflow instance.</param>
        /// <returns></returns>
        public Collection<SR.Job> GetWorkflowJobInstances(Guid workflowId)
        {
            if (workflowId == Guid.Empty)
            {
                throw new ArgumentNullException("workflowId");
            }
            return this.GetWorkflowInstances(workflowId);
        }

        /// <summary>
        /// Delete the specified workflow.
        /// </summary>
        /// <param name="workflowId">The workflow instance.</param>
        public void DeleteWorkflow(Guid workflowId)
        {
            if (workflowId == Guid.Empty)
            {
                throw new ArgumentNullException("workflowId");
            }

            this.SoftDeleteWorkflow(workflowId);
        }

        /// <summary>
        /// Open the composer with the required workflow.
        /// </summary>
        /// <param name="workflowId"></param>
        public void OpenComposerForEdit(Guid workflowId)
        {
            if (workflowId == Guid.Empty)
            {
                throw new ArgumentNullException("workflowId");
            }
            WorkflowManagerService.OpenComposer(workflowId);
        }

        /// <summary>
        /// Open the monitor window to check the progress of the workflow.
        /// </summary>
        /// <param name="jobId"></param>
        public void OpenMonitor(Guid jobId)
        {
            if (jobId == Guid.Empty)
            {
                throw new ArgumentNullException("jobId");
            }
            this.OpenMonitorWindow(jobId);
        }

        /// <summary>
        /// Open the provenance window.
        /// </summary>
        /// <param name="jobId">The job for which the provenance is to be shown.</param>
        public void OpenProvenanceWindow(Guid jobId)
        {
            if (jobId == Guid.Empty)
            {
                throw new ArgumentNullException("jobId");
            }
            this.OpenProvenanceApp(jobId);
        }

        /// <summary>
        /// Terminate the running job.
        /// </summary>
        /// <param name="jobId"></param>
        public void TerminateJob(Guid jobId)
        {
            if (jobId == Guid.Empty)
            {
                throw new ArgumentNullException("jobId");
            }
            this.TerminateSelectedjob(jobId);
        }

        /// <summary>
        /// Deletes the job instance. Valid only for completed jobs.
        /// </summary>
        /// <param name="jobId">The job to be deleted.</param>
        public void DeleteJob(Guid jobId)
        {
            if (jobId == Guid.Empty)
            {
                throw new ArgumentNullException("jobId");
            }
            this.DeleteSelectedJob(jobId);
        }

        /// <summary>
        ///  Retrieve the nodes in which the executer service is running.
        /// </summary>
        /// <returns>Collection of nodes.</returns>
        public Collection<SR.Machine> GetAllMachines(bool? isInteractive)
        {
            if (null == isInteractive)
            {
                List<SR.Machine> machineList = new List<SR.Machine>();
                try
                {
                    machineList = SR.Machine.LoadAll(this.registryConnection);
                }
                catch (SR.RecordNotFoundException)
                {
                    machineList = new List<SR.Machine>();
                }
                catch (Exception ex)
                {
                    TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                    TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                       TridentErrorConstants.ErrorNumber1000000011,
                       ManagementStudioResourceManager.GetString("MachineRetrieveError"));
                }

                return new Collection<SR.Machine>(machineList);
            }
            else
            {
                return this.GetNodes(isInteractive.Value) as Collection<SR.Machine>;
            }
        }

        /// <summary>
        /// Get all the interactive and noninteractive nodes with matching name
        /// </summary>
        /// <param name="hostname"></param>
        /// <returns></returns>
        public Collection<SR.Machine> GetAllMachinesWithName(string name)
        {
            return SR.Machine.CommonSearches.GetAllMachinesByName(this.registryConnection, name);
        }

        /// <summary>
        /// Retrieve all the users present in the registry.
        /// </summary>
        /// <returns>Collection of users.</returns>
        public Collection<SR.User> GetAllUsers(SR.User.ISearch.ISearchClause filter)
        {
            return this.GetUsers(filter);
        }

        /// <summary>
        /// Retrieve all the authenticated users present in the registry.
        /// </summary>
        /// <returns>Collection of users.</returns>
        public Collection<SR.User> GetAllAuthenticatedUsers()
        {
            return this.GetAuthenticatedUsers();
        }

        /// <summary>
        /// Retreive the workflow whose guid is specified.
        /// </summary>
        /// <param name="workflowId">The ID of the required workflow</param>
        /// <returns>The workflow required. </returns>
        public SR.Activity GetWorkflow(Guid workflowId)
        {
            if (workflowId == Guid.Empty)
            {
                throw new ArgumentNullException("workflowId");
            }
            return this.GetWorkflowById(workflowId);
        }

        /// <summary>
        /// Retreive the scheduled jobs from the registry.
        /// </summary>
        /// <returns></returns>
        public Collection<SR.JobSchedule> GetScheduledJobs(SR.JobSchedule.ISearch.ISearchClause filter)
        {
            Collection<SR.JobSchedule> schedules = null;
            try
            {
                Helper.RefreshSystemPolicy(this.registryConnection);
                if (TridentAuthentication.LoggedUserRole == UserRole.Admin)
                {
                    schedules = SR.JobSchedule.CommonSearches.GetAllScheduledJobs(this.registryConnection, filter);
                }
                else
                {
                    schedules = TridentAuthentication.LoggedInUser.GetAllScheduledJobs(filter);
                }
            }
            catch (TridentCustomException)
            {
                throw;
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                TridentErrorConstants.ErrorNumber1000000015,
                ManagementStudioResourceManager.GetString("ScheduleJobsRetrieveError"));
            }
            return schedules;
        }

        /// <summary>
        /// Retrieve the specified job from registry.
        /// </summary>
        /// <param name="scheduleId">The schedule id.</param>
        /// <returns>The registry object.</returns>
        public SR.JobSchedule GetSchedule(Guid scheduleId)
        {
            if (scheduleId == Guid.Empty)
            {
                throw new ArgumentNullException("scheduleId");
            }
            return this.GetScheduleById(scheduleId);
        }

        /// <summary>
        /// Delete the schedule from the registry.
        /// </summary>
        /// <param name="id">The ID of the schedule to be deleted.</param>
        public void DeleteSchedule(Guid scheduleId)
        {
            if (scheduleId == Guid.Empty)
            {
                throw new ArgumentNullException("scheduleId");
            }
            this.DeleteScheduleFromRegistry(scheduleId);
        }

        /// <summary>
        /// Check if the workflow is already deleted.
        /// </summary>
        /// <param name="workflowId">The workflow ID</param>
        /// <returns>True if the workflow has been deleted. False otherwise.</returns>
        public bool IsWorkflowDeleted(Guid workflowId)
        {
            if (workflowId == Guid.Empty)
            {
                throw new ArgumentNullException("workflowId");
            }

            try
            {
                SR.Activity selectedActivity = SR.Activity.Load(workflowId, this.registryConnection);
                return selectedActivity.IsDeleted;
            }
            catch (SR.RecordNotFoundException)
            {
                return true;
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
            }
            return false;
        }

        #endregion

        #region Private methods
        /// <summary>
        /// Retreive all the available workflows from the registry.
        /// </summary>
        /// <returns>Collection of all the workflows in the registry.</returns>
        private Collection<SR.Activity> GetWorkflows(SR.Activity.ISearch.ISearchClause filter)
        {
            Collection<SR.Activity> activityList = null;
            try
            {
                Helper.RefreshSystemPolicy(this.registryConnection);
                Collection<SR.Activity> tempActivityList = SR.Activity.CommonSearches.GetAllWorkflows(this.registryConnection, filter);
                if (tempActivityList != null)
                {

                    // Retrieve the latest and the labelled workflows only.
                    activityList = new Collection<SR.Activity>(tempActivityList.Where(activity =>
                    {
                        if (!string.IsNullOrEmpty(activity.VersionLabel))
                            return true;
                        else
                        {
                            return activity.IsLatestVersion();
                        }
                    }).ToList());
                }
            }
            catch (TridentCustomException)
            {
                throw;
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber100000001,
                  ManagementStudioResourceManager.GetString("AvailableWorkflowsRetrieveError"));
            }
            return activityList;
        }

        /// <summary>
        ///  Retreive all the currently running jobs from the registry.
        /// </summary>
        /// <returns>Collection of all the workflows in the registry.</returns>
        private Collection<SR.Job> GetRunningJobs(SR.Job.ISearch.ISearchClause filter)
        {
            Collection<SR.Job> jobList = null;
            try
            {
                Helper.RefreshSystemPolicy(this.registryConnection);
                if (TridentAuthentication.LoggedUserRole == UserRole.Admin)
                {
                    jobList = SR.Job.CommonSearches.GetRunningJobs(this.registryConnection, filter);
                }
                else
                {
                    jobList = TridentAuthentication.LoggedInUser.GetRunningJobs(filter);
                }
            }
            catch (TridentCustomException)
            {
                throw;
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                   TridentErrorConstants.ErrorNumber100000002,
                   ManagementStudioResourceManager.GetString("RunningJobsRetrieveError"));
            }

            return jobList;
        }

        /// <summary>
        /// Retreive the deleted workflows from the registry.
        /// </summary>
        /// <returns>Collection of all the deleted workflows.</returns>
        private Collection<SR.Activity> GetAllDeletedWorkflows(SR.Activity.ISearch.ISearchClause filter)
        {
            Collection<SR.Activity> activityList = null;
            try
            {
                Helper.RefreshSystemPolicy(this.registryConnection);
                Collection<SR.Activity> tempList = null;
                if (TridentAuthentication.LoggedUserRole == UserRole.Admin)
                {
                    tempList = SR.Activity.CommonSearches.GetDeletedWorkflows(this.registryConnection, filter);
                }
                else if (TridentAuthentication.LoggedUserRole == UserRole.NormalUser)
                {
                    tempList = TridentAuthentication.LoggedInUser.GetDeletedWorkflows(filter);
                }

                // Remove the workflows which are not the latest versions or are not labelled.
                if (tempList != null)
                {
                    for (int i = 0; i < tempList.Count; i++)
                    {
                        SR.Activity deletedWorkflow = tempList[i];
                        if (deletedWorkflow.IsLatestVersion() || !string.IsNullOrEmpty(deletedWorkflow.VersionLabel))
                        {
                            if (activityList == null)
                            {
                                activityList = new Collection<SR.Activity>();
                            }
                            activityList.Add(deletedWorkflow);
                        }
                    }
                }
            }
            catch (TridentCustomException)
            {
                throw;
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                   TridentErrorConstants.ErrorNumber100000003,
                   ManagementStudioResourceManager.GetString("DeletedWorkflowsRetrieveError"));
            }

            return activityList;
        }

        /// <summary>
        /// Retrieve the completed jobs from the registry.
        /// </summary>
        /// <returns>Collection of completed jobs.</returns>
        private Collection<SR.Job> GetMyCompletedJobs(SR.Job.ISearch.ISearchClause filter)
        {
            Collection<SR.Job> joblist = null;
            try
            {
                Helper.RefreshSystemPolicy(this.registryConnection);
                if (TridentAuthentication.LoggedUserRole == UserRole.Admin)
                {
                    joblist = SR.Job.CommonSearches.GetCompletedJobs(this.registryConnection, filter);
                }
                else
                {
                    joblist = TridentAuthentication.LoggedInUser.GetCompletedJobs(filter);
                }
            }
            catch (TridentCustomException)
            {
                throw;
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                   TridentErrorConstants.ErrorNumber100000004,
                   ManagementStudioResourceManager.GetString("CompletedJobsRetrieveError"));
            }
            return joblist;
        }

        /// <summary>
        /// Retreive the jobs of the specified workflow.
        /// </summary>
        /// <param name="guid">The specified workflow.</param>
        /// <returns>Collection of the jobs.</returns>
        private Collection<SR.Job> GetWorkflowInstances(Guid guid)
        {
            try
            {
                SR.Activity selectedActivity = SR.Activity.Load(guid, this.registryConnection);
                List<SR.Activity> allVersions = new List<SR.Activity>();
                allVersions.Add(selectedActivity);
                SR.Activity.GetOlderActivityVersions(selectedActivity, allVersions);

                List<SR.Job> allJobs = new List<SR.Job>();
                foreach (SR.Activity activity in allVersions)
                {
                    SR.ActivityInstanceCollection<SR.Activity> activityInstances = activity.Instances;
                    var results = from activityInstance in activityInstances
                                  from job in activityInstance.Jobs
                                  where !job.IsDeleted && (job.Status == SR.JobStatus.Aborted || job.Status == SR.JobStatus.Completed)
                                  select job;

                    allJobs.AddRange(results.ToList());
                }

                return new Collection<SR.Job>(allJobs);
            }
            catch (SR.RecordNotFoundException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                    TridentErrorConstants.ErrorNumber100000005,
                    ManagementStudioResourceManager.GetString("AvailableWorkflowsJobRetrieveError"));
            }
            catch (TridentCustomException)
            {
                throw;
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                   TridentErrorConstants.ErrorNumber100000005,
                   ManagementStudioResourceManager.GetString("AvailableWorkflowsJobRetrieveError"));
            }
            return null;
        }

        /// <summary>
        /// Delete the specified workflow.
        /// </summary>
        /// <param name="workflowToBeDeleted">The workflow to be deleted.</param>
        private void SoftDeleteWorkflow(Guid workflowToBeDeleted)
        {
            try
            {
                SR.Activity selectedActivity = SR.Activity.Load(workflowToBeDeleted, this.registryConnection);

                WorkflowComposer.DeleteWorkflow(selectedActivity);
            }
            catch (SR.RecordNotFoundException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                    TridentErrorConstants.ErrorNumber100000006,
                    ManagementStudioResourceManager.GetString("AvailableWorkflowDeleteError"));
            }
            catch (TridentCustomException)
            {
                throw;
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                   TridentErrorConstants.ErrorNumber100000006,
                   ManagementStudioResourceManager.GetString("AvailableWorkflowDeleteError"));
            }
        }

        /// <summary>
        /// Restores the soft deleted Workflow. 
        /// </summary>
        /// <param name="workflowId">Guid of Workflow Id</param>
        public void RestoreWorkflow(Guid workflowId)
        {
            try
            {
                string newWorkflowLabel = string.Empty;
                SR.Activity workflow = SR.Activity.Load(workflowId, this.registryConnection);
                Collection<SR.Activity> workflows = null;

                // If a workflow is already created with the same name or version label by the time restore is called
                // then add date time stamps to the label.
                if (string.IsNullOrEmpty(workflow.VersionLabel))
                {
                    workflows = workflow.Namespaces[0].GetWorkflows(workflow.Name);

                    if (workflows != null && workflows.Count > 0)
                    {
                        bool changeName = false;
                        foreach (SR.Activity duplicateWorkflow in workflows)
                        {
                            if (duplicateWorkflow.IsLatestVersion())
                            {
                                changeName = true;
                                break;
                            }
                        }
                        if (changeName)
                        {
                            workflow.Name = string.Concat(workflow.Name, DateTime.Now.ToString(DATETIMEFORMAT, CultureInfo.CurrentCulture));
                        }
                    }
                }
                else
                {
                    workflows = workflow.Namespaces[0].GetWorkflows(workflow.Name,
                        workflow.VersionLabel);
                    if (workflows != null && workflows.Count > 0)
                    {
                        workflow.VersionLabel = string.Concat(workflow.VersionLabel, DateTime.Now.ToString(DATETIMEFORMAT, CultureInfo.CurrentCulture));
                    }
                }

                if (workflow != null)
                {
                    workflow.IsDeleted = false;
                    workflow.Save();
                }
            }
            catch (SR.RecordNotFoundException)
            {
                throw new TridentCustomException("Workflow not exists");
            }
            catch (TridentCustomException)
            {
                throw;
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex, TridentErrorConstants.ErrorNumber1000000067, "Error while restoring the workflow");
            }
        }



        /// <summary>
        /// Purge the soft deleted Workflow. 
        /// </summary>
        /// <param name="workflowId">Guid of Workflow Id</param>
        public void PurgeWorkflow(Guid workflowId)
        {
            try
            {
                SR.Activity workflow = SR.Activity.Load(workflowId, this.registryConnection);

                // Get all older versions of the workflow.
                Collection<SR.Activity> versionCollection = new Collection<SR.Activity>();
                versionCollection.Add(workflow);
                workflow.GetVersionsToDelete(versionCollection);

                // Clear all version relationships.
                foreach (SR.Activity activity in versionCollection)
                {
                    activity.NewerVersions.Clear();
                }

                // As a workaround we are fetching the child of the last activity and clearing
                // its newer versions.
                SR.Activity act = versionCollection.ElementAt(versionCollection.Count - 1);

                if (act.OlderVersions.Count > 0)
                {
                    SR.Activity oldVersion = act.OlderVersions[0].Activity_1;
                    oldVersion.NewerVersions.Clear();
                }

                // Clear other relationships and delete the workflow.
                foreach (SR.Activity activity in versionCollection)
                {
                    if (activity != null)
                    {
                        // Delete activity sequences.
                        foreach (SR.ActivitySequence activityseq in activity.ActivitySequences)
                        {
                            this.DeleteActivitySequence(activityseq);
                        }

                        // Delete all activity instance and all corresponding relationships.
                        foreach (SR.ActivityInstance activityInstance in activity.Instances)
                        {
                            // Delete all the jobs related to this activity instance.
                            foreach (SR.Job job in activityInstance.Jobs)
                            {
                                // Delete all activity instance relationships
                                job.ActivityInstances.Clear();
                                // Delete additional parameters relationships
                                foreach (SR.AdditionalParameter parameter in job.AdditionalParameters)
                                {
                                    parameter.Delete();
                                }
                                // Delete the job.
                                job.Delete();
                            }
                            // Delete activity instance parameters relationships.
                            foreach (SR.ActivityInstanceParameter parameter in activityInstance.ActivityInstanceParameters)
                            {
                                parameter.Delete();
                            }
                            // Delete all associated Data Products
                            foreach (SR.DataProduct product in activityInstance.Outputs)
                            {
                                // Delete the data product bindings
                                foreach (SR.DataProductBinding binding in product.DataProductBindings)
                                {
                                    binding.Delete();
                                }
                                // Delete the data product details.
                                foreach (SR.DataProductDetail detail in product.DataProductDetails)
                                {
                                    detail.Delete();
                                }
                                // Delete the preview and content blobs.
                                product.DeleteBlobs();
                                // Delete the data product itself.
                                product.Delete();
                            }
                            // Delete the activity instance.
                            activityInstance.Delete();
                        }


                        // Delete associated icon blobs.
                        activity.DeleteIconBlobs();

                        // Delete the activity acls.
                        Collection<SR.ActivityACL> activityAcls = activity.GetAllACLs();


                        if (activityAcls != null)
                        {
                            foreach (SR.ActivityACL acl in activityAcls)
                            {
                                acl.Delete();
                            }
                        }

                        // Delete the activity itself.
                        activity.Delete();
                    }
                }
            }
            catch (SR.RecordNotFoundException)
            {
                throw new TridentCustomException("Workflow not exists");
            }
            catch (TridentCustomException)
            {
                throw;
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex, TridentErrorConstants.ErrorNumber1000000067, "Error while purging the workflow");
            }
        }

        private void DeleteActivitySequence(SR.ActivitySequence activitySequence)
        {
            if (activitySequence != null) // && activitySequence.ActivitySequences.Count > 0)
            {
                foreach (SR.ParameterAssignment paramAssignment in activitySequence.ParameterAssignments)
                {
                    paramAssignment.Delete();
                }

                foreach (SR.ActivitySequence activityseq in activitySequence.ActivitySequences)
                {
                    this.DeleteActivitySequence(activityseq);
                }

                activitySequence.Delete();
            }
        }

        /// <summary>
        /// Open the trident composer window.
        /// </summary>
        /// <param name="selectedWorkflow">The default worklfow to open.</param>
        [EnvironmentPermissionAttribute(SecurityAction.LinkDemand, Unrestricted = true)]
        private static void OpenComposer(Guid selectedWorkflow)
        {
            try
            {
                // get app name from config file.
                string appName = ConfigurationManager.AppSettings["ComposerApplication"];

                // Get the installation directory.
                string installDir = WorkflowManagerService.GetInstallationLocation();

                // Get the directory which contains the trident composer application.
                string appLocation = Path.Combine(installDir, appName);

                // Throw exception if the app doesnt exist.
                if (!File.Exists(appLocation))
                {
                    TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber1000000019,
                        ManagementStudioResourceManager.GetString("ComposerApplicationAbsent"));
                }

                string args = "-w" + " " + selectedWorkflow.ToString();

                // Open the composer.
                WorkflowManagerService.OpenApplication(appLocation, installDir, args);
            }
            catch (IOException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber100000007,
                  ManagementStudioResourceManager.GetString("AvailableWorkflowComposerOpenError"));
            }
            catch (InvalidOperationException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber100000007,
                  ManagementStudioResourceManager.GetString("AvailableWorkflowComposerOpenError"));
            }
            catch (System.ComponentModel.Win32Exception ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber100000007,
                  ManagementStudioResourceManager.GetString("AvailableWorkflowComposerOpenError"));
            }
        }

        /// <summary>
        /// Open the monitor window for the specified instance of the workflow.
        /// </summary>
        /// <param name="jobId">The Job id.</param>
        [EnvironmentPermissionAttribute(SecurityAction.LinkDemand, Unrestricted = true)]
        private void OpenMonitorWindow(Guid jobId)
        {
            bool isAlreadyTerminated = false;
            SR.Job job = null;

            try
            {
                // Check if the job has already completed.
                job = SR.Job.Load(jobId, this.registryConnection);

                // If the job has already completed or has been aborted.
                if (job.Status == SR.JobStatus.Completed || job.Status == SR.JobStatus.Aborted)
                {
                    isAlreadyTerminated = true;
                    return;
                }

                // get app name from config file.
                string appName = ConfigurationManager.AppSettings["RemoteMonitoringApplication"];

                // Get the installation directory.
                string installDir = WorkflowManagerService.GetInstallationLocation();

                // Get the directory which contains the monitorwindow application.
                string appLocation = Path.Combine(installDir, appName);

                // Throw exception if the app doesnt exist.
                if (!File.Exists(appLocation))
                {
                    TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber1000000018,
                        ManagementStudioResourceManager.GetString("MonitorApplicationAbsent"));
                }

                string args = "-job" + " " + jobId.ToString();

                // Open monitor window.
                WorkflowManagerService.OpenApplication(appLocation, installDir, args);
            }
            catch (IOException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber100000007,
                  ManagementStudioResourceManager.GetString("MonitorOpenError"));
            }
            catch (UnauthorizedAccessException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber100000007,
                  ManagementStudioResourceManager.GetString("MonitorOpenError"));
            }
            catch (SecurityException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber100000007,
                  ManagementStudioResourceManager.GetString("MonitorOpenError"));
            }
            catch (InvalidOperationException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber100000007,
                  ManagementStudioResourceManager.GetString("MonitorOpenError"));
            }
            catch (System.ComponentModel.Win32Exception ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber100000007,
                  ManagementStudioResourceManager.GetString("MonitorOpenError"));
            }
            finally
            {
                if (isAlreadyTerminated)
                {
                    TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber1000000016,
                        ManagementStudioResourceManager.GetString("RunningWorkflowCompletedMonitorError", job.Status.ToString()));
                }
            }
        }

        /// <summary>
        /// Open the provenance application.
        /// </summary>
        /// <param name="jobID">The job id.</param>
        private void OpenProvenanceApp(Guid jobID)
        {
            try
            {
                // get app name from config file.
                string appName = ConfigurationManager.AppSettings["ProvenanceApplication"];

                // Get the installation directory.
                string installDir = WorkflowManagerService.GetInstallationLocation();

                // Get the directory which contains the provenance application.
                string appLocation = Path.Combine(installDir, appName);

                // Throw exception if the app doesnt exist.
                if (!File.Exists(appLocation))
                {
                    TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber1000000039,
                        ManagementStudioResourceManager.GetString("ProvenanceApplicationAbsent"));
                }

                string args = "-job" + " " + jobID.ToString();

                // Open monitor window.
                WorkflowManagerService.OpenApplication(appLocation, installDir, args);
            }
            catch (IOException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber1000000040,
                  ManagementStudioResourceManager.GetString("ProvenanceLaunchError"));
            }
            catch (UnauthorizedAccessException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber1000000040,
                  ManagementStudioResourceManager.GetString("ProvenanceLaunchError"));
            }
            catch (SecurityException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber1000000040,
                  ManagementStudioResourceManager.GetString("ProvenanceLaunchError"));
            }
            catch (InvalidOperationException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber1000000040,
                  ManagementStudioResourceManager.GetString("ProvenanceLaunchError"));
            }
            catch (System.ComponentModel.Win32Exception ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                  TridentErrorConstants.ErrorNumber1000000040,
                  ManagementStudioResourceManager.GetString("ProvenanceLaunchError"));
            }
        }

        /// <summary>
        /// Open an application in a different process.
        /// </summary>
        /// <param name="appLocation">The location of the exe file.</param>
        /// <param name="workingDirectory">The working directory of the app.</param>
        /// <param name="argument">The command line args to be passed to the app.</param>
        [EnvironmentPermissionAttribute(SecurityAction.LinkDemand, Unrestricted = true)]
        public static void OpenApplication(string appLocation, string workingDirectory, string argument)
        {
            Process tridentProcess = new Process();

            // Process start info for the trident monitor.
            ProcessStartInfo monitorProcessStartInfo = new ProcessStartInfo();

            monitorProcessStartInfo.FileName = appLocation;

            monitorProcessStartInfo.WorkingDirectory = workingDirectory;

            monitorProcessStartInfo.Arguments = argument;

            // Launch app in a different process.
            tridentProcess.StartInfo = monitorProcessStartInfo;
            tridentProcess.Start();
        }

        /// <summary>
        /// Retreive the installation location of the app.
        /// </summary>
        /// <returns></returns>
        public static string GetInstallationLocation()
        {
            string subKey = ConfigurationManager.AppSettings["InstallationRegistrykey"]; ;

            string installationLocationKey = ConfigurationManager.AppSettings["InstallationSubKey"];

            return WorkflowManagerService.ReadRegistry(subKey, installationLocationKey);
        }

        /// <summary>
        /// Read the registry values given the keys.
        /// </summary>
        /// <param name="subkey">The sub key.</param>
        /// <param name="key">The key.</param>
        /// <returns>The value corresponding to the registry.</returns>
        private static string ReadRegistry(string subkey, string key)
        {
            // Opening the registry key
            RegistryKey regKey = Registry.LocalMachine;

            // Open a subKey as read-only
            RegistryKey sub = regKey.OpenSubKey(subkey);

            // If the RegistrySubKey doesn't exist -> (null)
            string result = null;

            if (sub != null)
            {
                // If the RegistryKey exists get its value
                // or null is returned.
                result = sub.GetValue(key.ToUpper(CultureInfo.InvariantCulture)) as string;
            }

            return result;
        }

        /// <summary>
        /// Terminate the specified job.
        /// </summary>
        /// <param name="jobToTerminate">The guid of the job to terminate.</param>
        private void TerminateSelectedjob(Guid jobToTerminate)
        {
            bool isAlreadyTerminated = false;
            SR.Job job = null;
            try
            {
                job = SR.Job.Load(jobToTerminate, this.registryConnection);

                // If the job has already completed or has been aborted.
                if (job.Status == SR.JobStatus.Completed || job.Status == SR.JobStatus.Aborted)
                {
                    isAlreadyTerminated = true;
                    return;
                }
                job.ErrorMessage = string.Format(CultureInfo.CurrentCulture, "{0} [{1} ({2})].", ManagementStudioResourceManager.GetString("JobTerminatedByUserMessage"),
                      TridentAuthentication.LoggedUserInUserName, TridentAuthentication.LoggedUserRole.ToString());
                job.Status = SR.JobStatus.StopPending;
                job.Save();
            }
            catch (SR.RecordNotFoundException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                    TridentErrorConstants.ErrorNumber100000009,
                    ManagementStudioResourceManager.GetString("RunningWorkflowTerminatedError"));
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                   TridentErrorConstants.ErrorNumber100000009,
                   ManagementStudioResourceManager.GetString("RunningWorkflowTerminatedError"));
            }
            finally
            {
                if (isAlreadyTerminated)
                {
                    TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber100000008,
                        ManagementStudioResourceManager.GetString("RunningWorkflowCompletedTerminateError", job.Status.ToString()));
                }
            }
        }

        /// <summary>
        /// Delete the job corresponding to the guid passed.
        /// </summary>
        /// <param name="jobToDelete"></param>
        private void DeleteSelectedJob(Guid jobToDelete)
        {
            try
            {
                SR.Job job = SR.Job.Load(jobToDelete, this.registryConnection);
                job.IsDeleted = true;
                job.Save();
            }
            catch (SR.RecordNotFoundException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                    TridentErrorConstants.ErrorNumber1000000010,
                    ManagementStudioResourceManager.GetString("CompletedJobDeleteError"));
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                   TridentErrorConstants.ErrorNumber1000000010,
                   ManagementStudioResourceManager.GetString("CompletedJobDeleteError"));
            }
        }


        /// <summary>
        /// Retrieve the nodes in which the executer service is running.
        /// </summary>
        /// <param name="IsInteractive">Is Interactive Workflow</param>
        /// <returns>Collection of machines.</returns>
        private Collection<SR.Machine> GetNodes(bool isInteractive)
        {
            Collection<SR.Machine> machineList = new Collection<SR.Machine>();
            try
            {
                machineList = SR.Machine.CommonSearches.GetOnlineMachines(this.registryConnection, isInteractive);
            }
            catch (SR.RecordNotFoundException)
            {

            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                   TridentErrorConstants.ErrorNumber1000000011,
                   ManagementStudioResourceManager.GetString("MachineRetrieveError"));
            }
            return machineList;
        }

        /// <summary>
        /// Retrieve the users from the registry.
        /// </summary>
        /// <returns>The collection of users.</returns>
        private Collection<SR.User> GetUsers(SR.User.ISearch.ISearchClause filter)
        {
            List<SR.User> userList = new List<SR.User>();
            try
            {
                SR.User.ISearch search = SR.User.ISearch.Create();
                if (null != filter)
                {
                    search.Query = filter;
                    userList = SR.User.Search(search, this.registryConnection);
                }
                else
                {
                    userList = SR.User.LoadAll(this.registryConnection);
                }
            }
            catch (SR.RecordNotFoundException)
            {
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                   TridentErrorConstants.ErrorNumber1000000017,
                   ManagementStudioResourceManager.GetString("UsersRetrieveError"));
            }
            return new Collection<SR.User>(userList); ;
        }


        /// <summary>
        /// Retrieve the authenticated users from the registry.
        /// </summary>
        /// <returns>The collection of authenticated users.</returns>
        private Collection<SR.User> GetAuthenticatedUsers()
        {
            Collection<SR.User> authenticatedUsers = new Collection<SR.User>();
            try
            {
                Collection<SR.User> userList = SR.User.CommonSearches.GetAllEnabledUsers(this.registryConnection);
                foreach (SR.User user in userList)
                {
                    // Check if the user is an authenticated user.
                    if (IsAuthenticatedUser(user))
                    {
                        authenticatedUsers.Add(user);
                    }
                    else
                    {
                        // Check if any of the groups that he belongs to is authenticated.
                        foreach (SR.Group group in user.Groups)
                        {
                            if (IsAuthenticatedUser(group))
                            {
                                authenticatedUsers.Add(user);
                                break;
                            }
                        }
                    }
                }
                return authenticatedUsers;
            }
            catch (SR.RecordNotFoundException)
            {
                return null;
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                   TridentErrorConstants.ErrorNumber1000000071,
                   ManagementStudioResourceManager.GetString("UsersRetrieveError"));
            }
            return null;
        }


        /// <summary>
        /// Determines whether [is authenticated user] [the specified principal].
        /// </summary>
        /// <param name="principal">The principal.</param>
        /// <returns>
        /// 	<c>true</c> if [is authenticated user] [the specified principal]; otherwise, <c>false</c>.
        /// </returns>
        private bool IsAuthenticatedUser(SR.ISecurityPrincipal principal)
        {
            SR.SystemPolicy policy = SR.SystemPolicy.Get(this.registryConnection);
            bool isAuthenticated = false;
            if (policy.Builtin.Administrators.Contains(principal) || policy.Builtin.Services.Contains(principal) || policy.Builtin.Users.Contains(principal))
            {
                isAuthenticated = true;
            }
            return isAuthenticated;
        }


        /// <summary>
        /// Retrieve the required workflow from registry.
        /// </summary>
        /// <param name="workflowId">The workflow ID.</param>
        /// <returns>The workflow object.</returns>
        private SR.Activity GetWorkflowById(Guid workflowId)
        {
            try
            {
                return SR.Activity.Load(workflowId, this.registryConnection);
            }
            catch (SR.RecordNotFoundException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                    TridentErrorConstants.ErrorNumber1000000012,
                    ManagementStudioResourceManager.GetString("WorkflowRetrieveError"));
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                   TridentErrorConstants.ErrorNumber1000000012,
                   ManagementStudioResourceManager.GetString("WorkflowRetrieveError"));
            }
            return null;
        }

        /// <summary>
        /// Retrieve the required machine from registry.
        /// </summary>
        /// <param name="machineId">The machine Id.</param>
        /// <returns>The machine object</returns>
        private SR.Machine GetMachineById(Guid machineId)
        {
            try
            {
                return SR.Machine.Load(machineId, this.registryConnection);
            }
            catch (SR.RecordNotFoundException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                TridentErrorConstants.ErrorNumber1000000013,
                ManagementStudioResourceManager.GetString("MachineFindError"));
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                TridentErrorConstants.ErrorNumber1000000013,
                ManagementStudioResourceManager.GetString("MachineFindError"));
            }
            return null;
        }


        /// <summary>
        /// Retrieve the required User from registry.
        /// </summary>
        /// <param name="machineId">The User Id.</param>
        /// <returns>The User object</returns>
        private SR.User GetUserById(Guid userId)
        {
            try
            {
                return SR.User.Load(userId, this.registryConnection);
            }
            catch (SR.RecordNotFoundException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                TridentErrorConstants.ErrorNumber1000000020,
                ManagementStudioResourceManager.GetString("UserRetrieveError"));
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                TridentErrorConstants.ErrorNumber1000000020,
                ManagementStudioResourceManager.GetString("UserRetrieveError"));
            }
            return null;
        }

        /// <summary>
        /// Retrieve the required schedule from registry.
        /// </summary>
        /// <param name="scheduleId">The schedule Id.</param>
        /// <returns>The schedule object</returns>
        private SR.JobSchedule GetScheduleById(Guid scheduleId)
        {
            try
            {
                return SR.JobSchedule.Load(scheduleId, this.registryConnection);
            }
            catch (SR.RecordNotFoundException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                TridentErrorConstants.ErrorNumber1000000021,
                ManagementStudioResourceManager.GetString("ScheduleRetrieveError"));
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                TridentErrorConstants.ErrorNumber1000000021,
                ManagementStudioResourceManager.GetString("ScheduleRetrieveError"));
            }
            return null;
        }

        /// <summary>
        /// Delete the schedule from registry. Set the status as cancelled. 
        /// The scheduler thread takes care of the actual deletion.
        /// </summary>
        /// <param name="id">The schedule ID.</param>
        private void DeleteScheduleFromRegistry(Guid id)
        {
            try
            {
                SR.JobSchedule scheduleToDelete = SR.JobSchedule.Load(id, this.registryConnection);
                scheduleToDelete.Status = SR.ScheduleStatus.Cancelled;
                scheduleToDelete.Save();
            }
            catch (SR.RecordNotFoundException ex)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                TridentErrorConstants.ErrorNumber1000000022,
                ManagementStudioResourceManager.GetString("ScheduleDeleteError"));
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                TridentErrorConstants.ErrorNumber1000000022,
                ManagementStudioResourceManager.GetString("ScheduleDeleteError"));
            }
        }

        /// <summary>
        /// Creates the schedule.
        /// </summary>
        /// <param name="JobName">Name of the job.</param>
        /// <param name="job">The job.</param>
        /// <returns></returns>
        public SR.JobSchedule CreateSchedule(string jobName, SR.Job job)
        {
            try
            {
                SR.JobSchedule schedule =
                    SR.JobSchedule.Create(jobName, job, this.registryConnection);
                return schedule;
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                TridentErrorConstants.ErrorNumber1000000022,
                ManagementStudioResourceManager.GetString("CreateScheduleError"));
            }

            return null;
        }

        /// <summary>
        /// Creates the activity instance parameter.
        /// </summary>
        /// <param name="activityId">The activity id.</param>
        /// <param name="paramName">Name of the param.</param>
        /// <param name="paramValue">The param value.</param>
        /// <param name="activityUniqueName">Name of the activity unique.</param>
        /// <param name="activityInstance">The activity instance.</param>
        public void CreateActivityInstanceParameter(string paramValue, SR.ActivityInstance activityInstance, SR.ParameterAssignment assignedParameter)
        {
            try
            {
                SR.ActivityInstanceParameter reqParam = SR.ActivityInstanceParameter.Create(
                    paramValue,
                    activityInstance,
                    assignedParameter,
                    this.registryConnection);

                reqParam.Save();
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                TridentErrorConstants.ErrorNumber1000000022,
                ManagementStudioResourceManager.GetString("CreateActivityInstanceParameterError"));
            }
        }

        /// <summary>
        /// Gets all assigned parameters.
        /// </summary>
        /// <returns></returns>
        public Collection<SR.ParameterAssignment> GetAllParameterAssignments(SR.ActivitySequence baseActivitySequence)
        {
            List<SR.ParameterAssignment> assignedParameters = new List<SR.ParameterAssignment>();
            try
            {
                assignedParameters = this.GetParameterAssignments(baseActivitySequence, assignedParameters);
            }
            catch (Exception ex)
            {
                TridentErrorHandler.ProcessKnownExceptionsInBusinessLogic(ex);
                TridentErrorHandler.HandleAndThrowBusinessLogicException(ex,
                TridentErrorConstants.ErrorNumber1000000022,
                ManagementStudioResourceManager.GetString("CreateActivityInstanceParameterError"));
            }

            return new Collection<SR.ParameterAssignment>(assignedParameters);
        }

        /// <summary>
        /// Gets the params.
        /// </summary>
        /// <param name="baseActivitySequence">The base activity sequence.</param>
        private List<SR.ParameterAssignment> GetParameterAssignments(SR.ActivitySequence baseActivitySequence, List<SR.ParameterAssignment> assignedParameters)
        {
            foreach (SR.ParameterAssignment paramAssign in baseActivitySequence.ParameterAssignments)
            {
                if (paramAssign.ActivityParameter.Direction == SR.DirectionType.Input && !paramAssign.IsBound)
                {
                    assignedParameters.Add(paramAssign);
                }
            }

            if (baseActivitySequence.Activity.IsComposite || baseActivitySequence.Activity.IsWorkflow)
            {
                foreach (SR.ActivitySequence child in baseActivitySequence.Children)
                {
                    this.GetParameterAssignments(child, assignedParameters);
                }
            }

            return assignedParameters;
        }


        #endregion
    }
}
